#include "mystdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>

//                          绝对路径          打开模式
MY_FILE *my_fopen(const char *path, const char *mode){
  
  //1、识别标志位，确定文件打开模式
  int flag = 0;
  if(strcmp(mode,"r")==0){
    flag |= O_RDONLY;
  }else if(strcmp(mode,"w")==0){
    flag |= (O_CREAT | O_WRONLY | O_TRUNC);
  }else if(strcmp(mode,"a")==0){
    flag |= (O_CREAT | O_WRONLY | O_APPEND);
  }else{
    //"r+"  "w+"  "a+"
  }
  
  //2、打开文件
  //设置创建出来的文件的权限
  mode_t m = 0666;
  //判断文件需不需要创建
  int fd = 0;
  if(flag & O_CREAT){
    fd = open(path,flag,m);
  }else{
    fd = open(path,flag);
  }

  //3、打开失败
  if(fd < 0){
    return NULL;
  }

  //4、打开成功返回MY_FILE对象
  //构造对象
  MY_FILE *mf = (MY_FILE*)malloc(sizeof(MY_FILE));
  //构造失败
  if(mf == NULL){
    //用文件描述符关闭当前打开的文件
    close(fd);
    return NULL;
  }

  //5、初始化MY_FILE对象
  mf->fd = fd;
  //设置刷新方式
  //mf->flags = 0;
  //mf->flags |= BUFF_LINE
  mf->flags = BUFF_LINE;
  //初始化缓冲区
  //mf->outputbuffer[0] = 0;
  memset(mf->outputbuffer,'\0',sizeof(mf->outputbuffer));
  mf->current = 0;
  //6、返回MY_FILE对象
  return mf;

}

int my_fflush(MY_FILE *fp){
  assert(fp);

  //int n = write(fp->fd, fp->outputbuffer, fp->current);
  //fp->current -= n;
  
  write(fp->fd, fp->outputbuffer, fp->current);
  //每次写完后清空文件缓冲区
  fp->current = 0;
  return 0;
}

//                        字符串  写入字符串大小  写入字符串的个数    文件指针
size_t my_fwrite(const void *ptr, size_t size, size_t nmemb, MY_FILE *stream){
  //1、判断缓冲区是否已满，如果已满，刷新缓冲区，如果未满，写入缓冲区
  //刷新缓冲区
  if(stream->current == NUM){
    my_fflush(stream);
  }
  //根据缓冲区剩余情况，写入缓冲区
  size_t user_size = size * nmemb;
  size_t my_size = NUM - stream->current;
  size_t writen = 0;
  //当剩余空间大于等于所需空间，直接写入
  if(my_size >= user_size){
    memcpy(stream->outputbuffer + stream->current, ptr, user_size);
    //2、更新计数器字段
    stream->current += user_size;
    writen = user_size;
  }else{ 
    memcpy(stream->outputbuffer + stream->current, ptr, my_size); 
    //2、更新计数器字段
    stream->current += my_size;
    writen = my_size;
  }

  //3、如果缓冲区满了，刷新缓冲区
  if(stream->flags & BUFF_ALL){
    if(stream->current == NUM){
      my_fflush(stream);
    }else if(stream->flags & BUFF_LINE){
      if(stream->outputbuffer[stream->current-1] == '\n'){
        my_fflush(stream);
      }
    }else{
      //...
    }
  }

  //返回写入个数
  return writen;
}
//                  文件指针
int my_fclose(MY_FILE *fp){
  assert(fp);

  //1、刷新缓冲区
  if(fp->current > 0){
    my_fflush(fp);
  }

  //2、关闭文件
  close(fp->fd);

  //3、释放堆空间 -- free
  free(fp);

  //(4、指针置空)
  //fp=NULL;
  
  return 0;
  
}
